<?php
    use_model('roles','users');

    class Acl extends ActiveRecord {
        
        function Acl()
        {
            $conf = array('table'=>DB_PREFIX.'acl');
            $this->ActiveRecord($conf);
        }
        
        function validate()
        {
            $this->validates_presence_of('acl_name');
            $this->validates_uniqueness_of('acl_name');
        }
        
        // static function
        /**
         * @param string or int $acl
         * @param int $user_id
         */
        function has_access_to($acl_name, $user_id)
        {
            $acl = new Acl();
            $roles = new Roles();
            
            // retrieve acl_id
            $acl_id = $acl->db->GetOne('SELECT id FROM `'.$this->table.'` WHERE acl_name=?',array($acl_name));
            if (!$acl_id) return false;

            
            // find all roles user has then find if any of those roles have access. eek
            $user_roles = $roles->get_user_role_ids($user_id);
            
            $has_access = false;
            
            // role access is inherited
            if ( count($user_roles) > 0 ) 
            {
                $role_id_access = $acl->db->GetOne("SELECT 
                                                      COUNT(role_id)
                                                    FROM
                                                      `".DB_PREFIX."acls_roles`
                                                    WHERE
                                                      acl_id = ".$acl_id."
                                                    AND
                                                      denied = 0
                                                    AND
                                                      role_id IN (".implode(',',$user_roles).")
                                                    ");
                if ( $role_id_access > 0 )
                {
                    $has_access = true;
                }
            }
            
            // check user access now if its false
            if ( !$has_access )
            {
                $user_id_access = $acl->db->GetOne("SELECT 
                                                       COUNT(user_id) 
                                                     FROM 
                                                       `".DB_PREFIX."acls_users` 
                                                     WHERE
                                                       acl_id = ?
                                                     AND
                                                       denied = 0
                                                     AND
                                                       user_id=?",
                                                     array($acl_id,$user_id));
                 if ( $user_id_access > 0 )
                 {
                     $has_access = true;
                 }                                                     
            }
                        
            return $has_access;

        }                
        
        function get_all_acls()
        {
            return $this->find(array('search'=>'all','order'=>'acl_name'));
        }                
        
        function grant_user_access($acl_id,$user_id)
        {
            // check if exists first, then insert deny
            $exists = $this->db->GetOne('SELECT 
                                           user_id 
                                         FROM 
                                           `'.DB_PREFIX.'acls_users` 
                                         WHERE 
                                           user_id=?
                                         AND
                                           acl_id=?',
                                         array($user_id,$acl_id));                                 
            if ( $exists )
            {
                $this->db->Execute('UPDATE 
                                      `'.DB_PREFIX.'acls_users` 
                                    SET denied = 0 
                                    WHERE
                                      acl_id = ?
                                    AND
                                      user_id = ?',
                                    array($acl_id,$user_id));                
            } else {
                $this->db->Execute('INSERT 
                                    INTO `'.DB_PREFIX.'acls_users` 
                                      (acl_id, user_id) 
                                    VALUES 
                                      (?,?)',
                                    array($acl_id,$user_id));
            }
        }   
        
        function deny_user_access($acl_id,$user_id)
        {
            // check if exists first, then insert deny
            $exists = $this->db->GetOne('SELECT 
                                           user_id 
                                         FROM 
                                           `'.DB_PREFIX.'acls_users` 
                                         WHERE 
                                           user_id=?
                                         AND
                                           acl_id=?',
                                         array($user_id,$acl_id));
            if ( $exists )
            {
                $this->db->Execute('UPDATE 
                                      `'.DB_PREFIX.'acls_users` 
                                    SET denied = 1 
                                    WHERE
                                      acl_id = ?
                                    AND
                                      user_id = ?',
                                    array($acl_id,$user_id));                
            } else {
                $this->db->Execute('INSERT 
                                    INTO `'.DB_PREFIX.'acls_users` 
                                      (acl_id, user_id) 
                                    VALUES 
                                      (?,?)',
                                    array($acl_id,$user_id));
            }
            
        }
        
        function clear_user_access($user_id)
        {
            $this->db->Execute('DELETE FROM `'.DB_PREFIX.'acls_users` WHERE user_id=?',array($user_id));
        }
        
        function grant_role_access($acl_id, $role_id) 
        {
            // check if exists first, then insert deny
            $exists = $this->db->GetOne('SELECT 
                                           role_id 
                                         FROM 
                                           `'.DB_PREFIX.'acls_roles`
                                         WHERE 
                                           role_id=?
                                         AND
                                           acl_id=?',
                                         array($role_id,$acl_id));
            if ( $exists )
            {
                 $this->db->Execute('UPDATE 
                                          `'.DB_PREFIX.'acls_roles` 
                                        SET denied = 0
                                        WHERE
                                          acl_id = ?
                                        AND
                                          role_id = ?',
                                        array($acl_id,$role_id));
            } else {
                $this->db->Execute('INSERT 
                                    INTO `'.DB_PREFIX.'acls_roles` 
                                      (acl_id, role_id) 
                                    VALUES 
                                      (?,?)',
                                    array($acl_id,$role_id));               
            }
        }
        
        function deny_role_access($acl_id, $role_id)
        {
            // check if exists first, then insert deny
            $exists = $this->db->GetOne('SELECT 
                                           role_id 
                                         FROM 
                                           `'.DB_PREFIX.'acls_roles`
                                         WHERE 
                                           role_id=?
                                         AND
                                           acl_id=?',
                                         array($role_id,$acl_id));
            if ( $exists )
            {
                $this->db->Execute('UPDATE 
                                      `'.DB_PREFIX.'acls_roles` 
                                    SET denied = 1 
                                    WHERE
                                      acl_id = ?
                                    AND
                                      role_id = ?',
                                    array($acl_id,$role_id));
                
            } else {
                $this->db->Execute('INSERT 
                                    INTO `'.DB_PREFIX.'acls_roles` 
                                      (acl_id, role_id) 
                                    VALUES 
                                      (?,?)',
                                    array($acl_id,$role_id));
            }
        }
        
        function clear_role_access($role_id)
        {
            $this->db->Execute('DELETE 
                                FROM `'.DB_PREFIX.'acls_roles` 
                                WHERE 
                                  role_id=?',
                                array($role_id));
        }
        
        // get all acl that role has access to
        function get_role_access($role_id)
        {
            return $this->db->GetCol('SELECT 
                                        acl_id 
                                      FROM `'.DB_PREFIX.'acls_roles`
                                      WHERE 
                                        denied=0 
                                      AND 
                                        role_id=?',
                                      array($role_id));
        }
        
        // get all acl that user has access to.
        function get_user_access($user_id)
        {
            // first get user access
            $user_access = $this->db->GetCol('SELECT 
                                                acl_id 
                                              FROM `'.DB_PREFIX.'acls_users` 
                                              WHERE 
                                                denied=0 
                                              AND 
                                                user_id=?',
                                              array($user_id));
            // get acl that user is specifically denied from
            $user_denied_access =  $this->db->GetCol('SELECT 
                                                        acl_id 
                                                      FROM `'.DB_PREFIX.'acls_users` 
                                                      WHERE 
                                                        denied=1
                                                      AND 
                                                        user_id=?',
                                                      array($user_id));
            $denied = '';
            if ( count($user_denied_access) > 0 )
            {
                $denied = " AND acl_id NOT IN (".implode(',', $user_denied_access).")";
            }
            
            // now get user roles, and the permissions for the roles
            // and then merge the arrays
            $roles              = new Roles();
            $user_roles         = $roles->get_user_role_ids($user_id);
            $user_roles_access  = array();
            if ( count($user_roles) > 0 )
            {
                $user_roles_access = $this->db->GetCol("SELECT 
                                                          acl_id 
                                                        FROM `".DB_PREFIX."acls_roles` 
                                                        WHERE 
                                                          denied=0 
                                                        AND
                                                          role_id IN (".implode(',', $user_roles).")
                                                        $denied");
            }

            $the_access = array_merge($user_access,$user_roles_access);
            return array_unique($the_access);
        }
                        
    }

?>